{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Unusual Gates like $X(0)^{1.2n(1)}$ or sqrt(iSWAP)\n",
    "\n",
    "The purpose of this notebook is to illustrate 2 new members\n",
    "in the set of gates that Qubiter recognizes. The 2 gates are\n",
    "\n",
    "1. an arbitrary matrix U2 in U(2), parametrized as \n",
    "$U2 = \\exp(i[ \\theta_0 + \\theta_1\\sigma_X + \\theta_2\\sigma_Y + \\theta_3\\sigma_Z])$ \n",
    "for real $\\theta_j$, where $\\sigma_X, \\sigma_Y, \\sigma_Z$ are the Pauli matrices.\n",
    "2. a generalization of SWAP(0, 1) which I call SWAY(0, 1). SWAY includes SWAP, sqrt(SWAP), iSWAP, sqrt(iSWAP) etc. I discuss SWAY more precisely below.\n",
    "\n",
    "The Qubiter simulator can now handle both of these gates with any number of controls of type T or F\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Importance of $\\theta_0$ when U2 has controls\n",
    "Qubiter previously included ROTN, which is a U2 with $\\theta_0=0$, which means ROTN is an \n",
    "element of SU(2), i.e., the Special 2-dim unitaries whose determinant is 1. Quantum mechanics does not\n",
    "care about global phases, so why would we want a U2 with non-zero $\\theta_0$?\n",
    "Because when we attach one or more controls to a U2 with non-zero $\\theta_0$,\n",
    "the controls place conditions on that $\\theta_0$, so the $\\theta_0$ now has a physical \n",
    "significance and can no longer be dropped. For example, \n",
    "$$[e^{i\\frac{\\pi}{2} \\sigma_Z(0)}]^{n(1)} = [i\\sigma_Z(0)]^{n(1)}= i^{n(1)}\\sigma_Z(0)^{n(1)}$$\n",
    "is physically different from\n",
    "$$[-ie^{i\\frac{\\pi}{2} \\sigma_Z(0)}]^{n(1)}=\\sigma_Z(0)^{n(1)}$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## SWAY\n",
    "\n",
    "Recall that the swap of two qubits 0, 1, call it SWAP(1, 0), is defined by \n",
    "\n",
    "$$ SWAP = diag(1, \\sigma_X, 1) $$\n",
    "\n",
    ">NOTE: SWAP is qbit symmetric, meaning that SWAP(0,1) = SWAP(1,0)\n",
    "\n",
    "We define SWAY by\n",
    "\n",
    "$$ SWAY = diag(1, U2, 1) $$\n",
    "\n",
    "where U2 is the most general 2-dim unitary matrix satisfying\n",
    "$$\\sigma_X U2 \\sigma_X= U2$$\n",
    "If U2 is parametrized as\n",
    "\n",
    "$$U2 = \\exp(i[ \\theta_0 + \\theta_1\\sigma_X + \\theta_2\\sigma_Y + \\theta_3\\sigma_Z])$$ \n",
    "for real $\\theta_j$, then SWAY is qbit symmetric (SWAY(0,1)=SWAY(1,0)) iff $\\sigma_X U2 \\sigma_X= U2$ iff $\\theta_2=\\theta_3=0$.\n",
    "\n",
    "Just like \n",
    "\n",
    "```\n",
    "SWAP =\n",
    "X---@\n",
    "@---X\n",
    "X---@\n",
    "```\n",
    "\n",
    "one has\n",
    "\n",
    "```\n",
    "SWAY=\n",
    "X---@\n",
    "@---U2\n",
    "X---@\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we will test Qubiter's implementation of these two new types of gates.\n",
    "\n",
    "First change your working directory to the qubiter directory in your computer, and add its path to the path environment variable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/home/rrtucci/PycharmProjects/qubiter/qubiter/jupyter_notebooks\n",
      "/home/rrtucci/PycharmProjects/qubiter\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import sys\n",
    "print(os.getcwd())\n",
    "os.chdir('../../')\n",
    "print(os.getcwd())\n",
    "sys.path.insert(0,os.getcwd())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loaded OneQubitGate, WITHOUT autograd.numpy\n"
     ]
    }
   ],
   "source": [
    "from qubiter.SEO_writer import *\n",
    "from qubiter.SEO_simulator import *"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we define some constants that we will use later on."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "num_qbits = 5\n",
    "emb = CktEmbedder(num_qbits, num_qbits)\n",
    "trols = Controls(num_qbits)\n",
    "trols.bit_pos_to_kind = {3: True, 4: False}\n",
    "trols.refresh_lists()\n",
    "file_prefix = 'sway_test'\n",
    "g = np.pi/180\n",
    "rads_list1_ = ['#1', 20*g]\n",
    "rads_list1 = ['#1', 20*g, 0, 0]\n",
    "rads_list13 = ['#1', 20*g, 0, 40*g]\n",
    "rads_list123 = ['#1', 20*g, 30*g, 40*g]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we create a SEO_writer and write a 5 qubit circuit with it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "wr = SEO_writer(file_prefix, emb)\n",
    "wr.write_X(3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In English files, a U2 gate is represented by `U_2_`. In Picture files, it is represented\n",
    "by either U, Ux, Uy, Uz or Ph. U is used if $\\theta_1, \\theta_2, \\theta_3$ are all non-zero. \n",
    "Ux is used if $\\theta_1$ is non-zero but $\\theta_2=\\theta_3=0$.\n",
    "Ph is used if $\\theta_1=\\theta_2=\\theta_3=0$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "wr.write_U2(0, rads_list13)\n",
    "wr.write_U2(1, rads_list1)\n",
    "wr.write_controlled_one_qbit_gate(0, trols, OneQubitGate.u2, rads_list13)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Without a rads\\_list, write_controlled_qbit_swap() writes a controlled SWAP.\n",
    "With a rads\\_list, it writes a controlled SWAY\n",
    "\n",
    "In English files, a swap gate is represented by `SWAP`. In Picture files, a SWAP is represented by two single-chevron arrowheads pointing away from each other,\n",
    "\n",
    "$\\tt <---+---+--->$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "wr.write_qbit_swap(0, 1)\n",
    "wr.write_controlled_qbit_swap(0, 1, trols)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In English files, a sway gate is represented by `SWAY`. In Picture files, a SWAY is represented by 2 double-chevron arrowheads pointing away from each other,\n",
    "\n",
    "$\\tt <<--+---+-->>$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "wr.write_qbit_swap(0, 1, rads_list1_)\n",
    "wr.write_controlled_qbit_swap(0, 1, trols, rads_list1_)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "wr.close_files()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The above code wrote English and Picture files in the io_folder.\n",
    "\n",
    "1. <a href='../io_folder/sway_test_5_eng.txt'>../io_folder/sway_test_5_eng.txt</a>\n",
    "2. <a href='../io_folder/sway_test_5_ZLpic.txt'>../io_folder/sway_test_5_ZLpic.txt</a>\n",
    "\n",
    "We can ask wr to print them for us "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table style='font-family:monospace'><tr><td style='border-right:1px solid red;'>1</td><td style='text-align:left;'><pre>SIGX\tAT\t3</pre></td></tr><td style='border-right:1px solid red;'>2</td><td style='text-align:left;'><pre>U_2_\t#1\t20.000000\t0.000000\t40.000000\tAT\t0</pre></td></tr><td style='border-right:1px solid red;'>3</td><td style='text-align:left;'><pre>U_2_\t#1\t20.000000\t0.000000\t0.000000\tAT\t1</pre></td></tr><td style='border-right:1px solid red;'>4</td><td style='text-align:left;'><pre>U_2_\t#1\t20.000000\t0.000000\t40.000000\tAT\t0\tIF\t4F\t3T</pre></td></tr><td style='border-right:1px solid red;'>5</td><td style='text-align:left;'><pre>SWAP\t1\t0</pre></td></tr><td style='border-right:1px solid red;'>6</td><td style='text-align:left;'><pre>SWAP\t1\t0\tIF\t4F\t3T</pre></td></tr><td style='border-right:1px solid red;'>7</td><td style='text-align:left;'><pre>SWAY\t1\t0\tBY\t#1\t20.000000</pre></td></tr><td style='border-right:1px solid red;'>8</td><td style='text-align:left;'><pre>SWAY\t1\t0\tBY\t#1\t20.000000\tIF\t4F\t3T</pre></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "wr.print_eng_file(jup=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table style='font-family:monospace'><tr><td style='border-right:1px solid red;'>1</td><td style='text-align:left;'><pre>|   X   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>2</td><td style='text-align:left;'><pre>|   |   |   |   U</pre></td></tr><td style='border-right:1px solid red;'>3</td><td style='text-align:left;'><pre>|   |   |   Ux  |</pre></td></tr><td style='border-right:1px solid red;'>4</td><td style='text-align:left;'><pre>O---@---+---+---U</pre></td></tr><td style='border-right:1px solid red;'>5</td><td style='text-align:left;'><pre>|   |   |   <---></pre></td></tr><td style='border-right:1px solid red;'>6</td><td style='text-align:left;'><pre>O---@---+---<---></pre></td></tr><td style='border-right:1px solid red;'>7</td><td style='text-align:left;'><pre>|   |   |   <<-->></pre></td></tr><td style='border-right:1px solid red;'>8</td><td style='text-align:left;'><pre>O---@---+---<<-->></pre></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "wr.print_pic_file(jup=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following shows that class SEO_simulator recognizes the 2 new gates, with and without controls, and can multiply\n",
    "through them"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*********branch= pure\n",
      "total probability of state vector (=one if no measurements)= 1.000000\n",
      "dictionary with key=qubit, value=(Prob(0), Prob(1))\n",
      "{0: (0.960906, 0.039094),\n",
      " 1: (0.722135, 0.277865),\n",
      " 2: (1.0, -0.0),\n",
      " 3: (0.0, 1.0),\n",
      " 4: (1.0, -0.0)}\n"
     ]
    }
   ],
   "source": [
    "vman = PlaceholderManager(var_num_to_rads={1: np.pi/6})\n",
    "sim = SEO_simulator(file_prefix, num_qbits, verbose=False,\n",
    "                    vars_manager=vman)\n",
    "StateVec.describe_st_vec_dict(sim.cur_st_vec_dict)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "toc": {
   "colors": {
    "hover_highlight": "#DAA520",
    "running_highlight": "#FF0000",
    "selected_highlight": "#FFD700"
   },
   "moveMenuLeft": true,
   "nav_menu": {
    "height": "87px",
    "width": "252px"
   },
   "navigate_menu": true,
   "number_sections": true,
   "sideBar": true,
   "threshold": 4,
   "toc_cell": false,
   "toc_section_display": "block",
   "toc_window_display": false,
   "widenNotebook": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
